package cn.likun.kit;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Hashtable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.impl.SimpleLog;
import cn.likun.kit.validate.ValidateCommons;

public class Logger {

	private static boolean isCheckLog4jInit = false;
	private static boolean isLog4jInit = true;
	private static Hashtable<Class<?>, Log> simpleLogCache = new Hashtable<Class<?>, Log>();

	public static void trace(Class<?> clazz, String message) {
		trace(clazz, message, null);
	}

	public static void trace(Class<?> clazz, String message, Throwable e) {
		writeLog(clazz, message, e, SimpleLog.LOG_LEVEL_TRACE);
	}

	public static void debug(Class<?> clazz, String message) {
		debug(clazz, message, null);
	}

	public static void debug(Class<?> clazz, String message, Throwable e) {
		writeLog(clazz, message, e, SimpleLog.LOG_LEVEL_DEBUG);
	}

	public static void info(Class<?> clazz, String message) {
		info(clazz, message, null);
	}

	public static void info(Class<?> clazz, String message, Throwable e) {
		writeLog(clazz, message, e, SimpleLog.LOG_LEVEL_INFO);
	}

	public static void warn(Class<?> clazz, String message) {
		warn(clazz, message, null);
	}

	public static void warn(Class<?> clazz, String message, Throwable e) {
		writeLog(clazz, message, e, SimpleLog.LOG_LEVEL_WARN);
	}

	public static void error(Class<?> clazz, String message) {
		error(clazz, message, null);
	}

	public static void error(Class<?> clazz, String message, Throwable e) {
		writeLog(clazz, message, e, SimpleLog.LOG_LEVEL_ERROR);
	}

	public static void fatal(Class<?> clazz, String message) {
		fatal(clazz, message, null);
	}

	public static void fatal(Class<?> clazz, String message, Throwable e) {
		writeLog(clazz, message, e, SimpleLog.LOG_LEVEL_FATAL);
	}

	private static void writeLog(Class<?> clazz, String message, Throwable e, int level) {
		Log log = getLog(clazz);
		if (SimpleLog.LOG_LEVEL_TRACE == level) {
			if (log.isTraceEnabled()) {
				log.trace(message, e);
			}
		} else if (SimpleLog.LOG_LEVEL_DEBUG == level) {
			if (log.isDebugEnabled()) {
				log.debug(message, e);
			}
		} else if (SimpleLog.LOG_LEVEL_INFO == level) {
			if (log.isInfoEnabled()) {
				log.info(message, e);
			}
		} else if (SimpleLog.LOG_LEVEL_WARN == level) {
			if (log.isWarnEnabled()) {
				log.warn(message, e);
			}
		} else if (SimpleLog.LOG_LEVEL_ERROR == level) {
			if (log.isErrorEnabled()) {
				log.error(message, e);
			}
		} else if (SimpleLog.LOG_LEVEL_FATAL == level) {
			if (log.isFatalEnabled()) {
				log.fatal(message, e);
			}
		}
	}

	private static Log getLog(Class<?> clazz) {
		if (!isCheckLog4jInit) {
			ByteArrayOutputStream out = null;
			PrintStream outErr = null;
			try {
				Log checkLog = LogFactory.getLog(Logger.class);
				// 开始捕捉代码输出信息
				PrintStream backupErr = System.err;
				out = new ByteArrayOutputStream(1024);
				outErr = new PrintStream(out);
				System.setErr(outErr);
				checkLog.fatal("check log4j init");
				if (out.toString().indexOf("log4j:WARN Please initialize the log4j system properly") > -1) {
					isLog4jInit = false;
				}
				System.setErr(backupErr);
				// 结束捕捉代码输出信息
			} finally {
				isCheckLog4jInit = true;
				try {
					outErr.close();
					out.close();
				} catch (IOException e) {
					Logger.error(Logger.class, "IO 异常：", e);
				}
			}
		}
		Log log = null;
		if (isLog4jInit) {
			log = LogFactory.getLog(clazz);
		} else {
			log = simpleLogCache.get(clazz);
			if (ValidateCommons.isEmpty(log)) {
				log = new SimpleLog(clazz.getName());
				simpleLogCache.put(clazz, log);
			}
		}
		return log;
	}

}
